home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / brklyprl.lha / Emulator / top_level.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-14  |  16.9 KB  |  853 lines

  1.  
  2. /* Copyright (C) 1988, 1989 Herve' Touati, Aquarius Project, UC Berkeley */
  3.  
  4. /* Copyright Herve' Touati, Aquarius Project, UC Berkeley */
  5.  
  6. #include <sys/time.h>
  7. #include <sys/resource.h>
  8. #include <signal.h>
  9. #include <setjmp.h>
  10. #include <stream.h>
  11. #include "hash_table.h"
  12. #include "string_table.h"
  13. #include "tags.h"
  14. #include "instr.h"
  15. #include "scan.h"
  16. #include "memory.h"
  17. #include "inst_args.h"
  18. #include "inst_table.h"
  19. #include "assembler.h"
  20. #include "main.h"
  21. #include "top_level.h"
  22. #include "basics.h"
  23. #include "control.h"
  24. #include "compile.h"
  25. #include "arg_types.h"
  26. #ifdef WITH_GC
  27. #include "gc.h"
  28. #endif
  29.  
  30. Command commands[] = {
  31. #define NAMES
  32. #define use(String,ID,Function,ARGTYPE)\
  33.   {String, ID, &Function, ARGTYPE},
  34. #include "commands.h"
  35. #undef use
  36. #undef NAMES
  37. };
  38.  
  39. static Scan command_scanner;
  40. static HashTable command_ID;
  41. typedef int (*IPF)();
  42. extern PF set_new_handler(PF);
  43. extern void out_of_store();
  44. void init_commands()
  45. {
  46.   IPF signal(...);
  47.  
  48.   for (int i = 0; i < LAST_COMMAND; i++)
  49.     command_ID.bind(command_scanner.intern(commands[i].name), commands[i].ID);
  50.   signal(SIGINT, &service_interrupt);
  51.   signal(SIGILL, &service_illegal_instruction);
  52.   signal(SIGBUS, &service_bus_error);
  53.   signal(SIGSEGV, &service_segmentation_fault);
  54.   set_new_handler(&out_of_store);
  55. }
  56.  
  57. void execute_command()
  58. {
  59.   int ID = command_ID.get(command_scanner.intern_p0);
  60.   Command* C = &commands[ID];
  61.   int arg = instr_args[C->arg_type]->fill(command_scanner.p[1]);
  62.   (*(C->exec))(arg);
  63. }
  64.  
  65. char* prompt = "> ";
  66.  
  67. void DisplayMemSize(int)
  68. {
  69. #define use(Name,ID,Coeff,Reg,Type)\
  70.   cout << Name << " = " << memory_sizes[ID] << " words\n";
  71. #include "memory_sizes.h"
  72. #undef use  
  73. }  
  74.  
  75. extern void write_term(Cell);
  76.  
  77. int BREADTH_LIMIT = 8;
  78. void SetBreadth(int breadth)
  79. {
  80.   BREADTH_LIMIT = breadth;
  81. }
  82.  
  83. int DEPTH_LIMIT = 8;
  84. void SetDepth(int depth)
  85. {
  86.   DEPTH_LIMIT = depth;
  87. }
  88.  
  89. void PrintYReg(int index)
  90. {
  91.   write_term(E[index]);
  92.   cout << "\n";
  93. }
  94.  
  95.  /* in cells */
  96. int window_size = 1024;
  97. static int instr_trace_flag;
  98. static int call_trace_flag;
  99. static int print_xreg_flag;
  100. static int print_xreg_last;
  101. static int break_point_flag;
  102. static int profile_flag;
  103. static int arg_type_flag;
  104. int trace_heap_flag;
  105. static int trace_stack_flag;
  106. static int trace_gc_calls_flag;
  107. static ArgTypes ArgData;
  108. static Instr* break_point;
  109. static int last_xreg;
  110. static CellPtr H_window;
  111. static int count_reset_window;
  112. #define COUNT_SIZE 1024
  113. static int gc_calls_count[COUNT_SIZE];
  114.  
  115. void PrintXReg(int index)
  116. {
  117.   last_xreg = index;
  118.   write_term(X[index]);
  119.   cout << "\n";
  120. }
  121.  
  122. void DisplayToggles(int)
  123. {
  124.   if (instr_trace_flag) cerr << "instr trace on\n";
  125.   if (call_trace_flag) cerr << "call trace on\n";
  126.   if (print_xreg_flag) cerr << "xreg trace on\n";
  127.   if (profile_flag) cerr << "profiling on\n";
  128.   if (arg_type_flag) cerr << "arg types monitored\n";
  129.   if (trace_heap_flag) cerr << "Heap Max Traced\n";
  130.   if (trace_stack_flag) cerr << "Control Stack Max Traced\n";
  131. #ifdef WITH_GC
  132.   if (DISPLAY_GC) cerr << "GC Activity Traced\n";
  133.   if (CHECK_GC_LIMIT) cerr << "GC activations limited\n";
  134. #endif
  135.   if (break_point_flag)
  136.     cerr << "break point at " << (break_point - P0) << "\n";
  137.   if (trace_gc_calls_flag) {
  138.     cerr << "GC Calls Traced\n";
  139.     cerr << "Window Size is " << window_size / 256 << " KB\n";
  140.   }
  141. }
  142.  
  143. void ToggleTraceFlag(int atom)
  144. {
  145.   char* mode = (char*) atom;
  146.   switch (*mode) {
  147.   case 'g':
  148.     trace_gc_calls_flag = 1 - trace_gc_calls_flag;
  149.     break;
  150.   case 'i':
  151.     instr_trace_flag = 1 - instr_trace_flag;
  152.     break;
  153.   case 'c':
  154.     call_trace_flag = 1 - call_trace_flag;
  155.     break;
  156.   case 'x':
  157.     print_xreg_flag = 1 - print_xreg_flag;
  158.     print_xreg_last = last_xreg;
  159.     break;
  160.   case 'h':
  161.     trace_heap_flag = 1 - trace_heap_flag;
  162.     break;
  163.   case 's':
  164.     trace_stack_flag = 1 - trace_stack_flag;
  165.     break;
  166.   default:
  167.     cerr << "[gicxhs]: gc, instr, call, xregs, heap, control stacks\n";
  168.     break;
  169.   }
  170. }
  171.  
  172. void ToggleProfile(int)
  173. {
  174.   profile_flag = 1 - profile_flag;
  175. }
  176.  
  177. void RecordArgTypes(int)
  178. {
  179.   arg_type_flag = 1 - arg_type_flag;
  180.   if (arg_type_flag) {
  181.     ArgData.init();
  182.   }
  183. }
  184.  
  185. void ListProc(int)
  186. {
  187.   if (arg_type_flag) {
  188.     ArgData.print();
  189.   } else {
  190.     instr_args[ARG_PROC]->print_proc_table();
  191.   }
  192. }
  193.  
  194. void print_xregs(int last_xreg)
  195. {
  196.   for (int i = 0; i <= last_xreg; i++) {
  197.     cout << "X" << i << "->";
  198.     write_term(X[i]);
  199.     cout << "; ";
  200.   }
  201.   cout << "\n";
  202. }
  203.  
  204. void instr_trace(int xregs)
  205. {
  206.   cout << P - P0 << ": ";
  207.   instr_types[P->ID].print(*P);
  208.   (*P->exec)();
  209.   if (print_xreg_flag) print_xregs(xregs);
  210. }  
  211.  
  212. void call_trace()
  213. {
  214.   switch (P->ID) {
  215.   case EXECUTE_PROC:
  216.   case CALL:
  217.     int arity = instr_args[ARG_PROC]->get_arity(P->arg1);
  218.     instr_trace(arity - 1);
  219.     break;
  220.   default:
  221.     (*P->exec)();
  222.     break;
  223.   }
  224. }
  225.  
  226. HeapData heap_usage;
  227. static StackData stack_usage;
  228.  
  229. void init_gather_data()
  230. {
  231.   heap_usage.clear();
  232.   stack_usage.clear();
  233. }
  234.  
  235. void HeapUsage(int)
  236. {
  237.   if (! trace_heap_flag) {
  238.     cerr << "execute with trace h first\n";
  239.     return;
  240.   }
  241.   if (! heap_usage.end) {
  242.     heap_usage.end = 1;
  243.     heap_usage.enter(cellp(B[H_CP_OFFSET]), H);
  244.   }
  245.   heap_usage.print();
  246. }
  247.  
  248. void StackUsage(int)
  249. {
  250.   if (! trace_stack_flag) {
  251.     cerr << "execute with trace s first\n";
  252.     return;
  253.   }
  254.   stack_usage.print();
  255. }
  256.  
  257. inline void step() 
  258. {
  259.   if (profile_flag) {
  260.     P->count++;
  261.   }
  262.   if (arg_type_flag) {
  263.     if (P->ID == CALL || P->ID == EXECUTE_PROC) {
  264.       ArgData.fill(P->arg1);
  265.     }
  266.   }
  267.   if (trace_heap_flag) {
  268.     if (P->ID == FAIL) {
  269.       heap_usage.enter(cellp(B[H_CP_OFFSET]),H);
  270.     }
  271.   }
  272.   if (trace_stack_flag) {
  273.     if (P->ID == CALL || P->ID == EXECUTE_PROC) {
  274.       stack_usage.enter(E, B);
  275.     }
  276.   }
  277.   if (instr_trace_flag) {
  278.     instr_trace(print_xreg_last);
  279.   } else if (call_trace_flag) {
  280.     call_trace();
  281.   } else {
  282.     (*P->exec)();
  283.   }
  284.   if (trace_gc_calls_flag) {
  285.     if (P->ID == CALL || P->ID == EXECUTE_PROC) {
  286.       if (H > H_window + window_size) {
  287.     CellPtr b = B;
  288.     int count = 0;
  289.     cout << (int) H << " " << (int) H_window;
  290.     while (cellp(b[H_CP_OFFSET]) > H_window) {
  291.       cout << " " << b[H_CP_OFFSET];
  292.       b = b + FIXED_CP_SIZE + b[SIZE_CP_OFFSET];
  293.       count++;
  294.     }
  295.     cout << "\n";
  296.     if (count >= COUNT_SIZE) {
  297.       cerr << "Overflow in gc call buckets\n";
  298.       count = COUNT_SIZE - 1;
  299.     }
  300.     gc_calls_count[count]++;
  301.     H_window = H;
  302.       }
  303.     } else if (P->ID == FAIL) {
  304.       if (H < H_window) {
  305.     count_reset_window++;
  306.     H_window = H;
  307.       }
  308.     }
  309.   }
  310.   P++;
  311. }
  312.  
  313. void Step(int)
  314. {
  315.   step();
  316. }
  317.  
  318. void Next(int) 
  319. {
  320.   for (; P != break_point; P++) {
  321.     if (instr_trace_flag) instr_trace(print_xreg_last);
  322.     if (call_trace_flag) call_trace();
  323.     if (P->ID == CALL || P->ID == EXECUTE_PROC)
  324.       break;
  325.     (*P->exec)();
  326.   }
  327. }
  328.  
  329. void SetBreakPoint(int instr_number)
  330. {
  331.   break_point_flag = 1 - break_point_flag;
  332.   if (break_point_flag)
  333.     break_point = P0 + instr_number;
  334.   else
  335.     break_point = 0;
  336. }
  337.  
  338. void execute()
  339. {
  340.   for (; P != break_point; )
  341.     step();
  342. }
  343.  
  344. void Continue(int iter)
  345. {
  346.   iter = (iter < 1) ? 1 : iter;
  347.   for (int i = 0; i < iter; i++) {
  348.     step();
  349.     execute();
  350.   }
  351. }
  352.  
  353. void Reset(int)
  354. {
  355.   init_gather_data();
  356.   init_control_registers();
  357.   for (int i = 0; i < COUNT_SIZE; i++)
  358.     gc_calls_count[i] = 0;
  359.   count_reset_window = 0;
  360.   heap_usage.clear();
  361. }
  362.   
  363. extern void init_gather_data();
  364.  
  365. void Run(int)
  366. {
  367.   if(instr_args[ARG_PROC]->status == UNRESOLVED_ADDRESSES)
  368.     top_level_error("unknown procedure: can't execute");
  369.   init_control_registers();
  370.   init_gather_data();
  371.   execute();
  372. }
  373.  
  374. void Fast(int)
  375. {
  376.   extern void fast_execute();
  377.   if(instr_args[ARG_PROC]->status == UNRESOLVED_ADDRESSES)
  378.     top_level_error("unknown procedure: can't execute");
  379.   init_control_registers();
  380.   fast_execute();
  381. }
  382.  
  383. void PrintInstr(int)
  384. {
  385.   instr_types[P->ID].print(*P);
  386. }
  387.  
  388. void ListCode(int from)
  389. {
  390.   assembly_print(from, profile_flag);
  391. }
  392.  
  393. void assemble_file(char* filename, int mode)
  394. {
  395.   istream* new_cinp = get_loadable_file(filename, mode);
  396.   if (new_cinp == 0) {
  397.     cerr << filename << ".w ";
  398.     top_level_error("can't be found or made");
  399.   }
  400.   istream old_cin = cin;
  401.   cin = *new_cinp;
  402.   assembly();
  403.   cin = old_cin;
  404. }
  405.  
  406. void AssembleFile(int atom)
  407. {
  408.   assemble_file((char*) atom, LOAD_MODE);
  409.   init_control_registers();
  410. }
  411.  
  412. void CompileAndLoad(int atom)
  413. {
  414.   assemble_file((char*) atom, COMPILE_MODE);
  415.   init_control_registers();
  416. }
  417.  
  418. void Usage(int)
  419. {
  420. #define NAMES
  421. #define use(String,ID,Function,ArgID)\
  422.   cerr << String << ": " << instr_args[ArgID]->name << "\n";
  423. #include "commands.h"
  424. #undef use
  425. #undef NAMES
  426. }
  427.  
  428. #define use(Function,Type,sign,ORIGIN)\
  429. void Function(Type ptr)\
  430. {\
  431.   cerr << sign(ptr - ORIGIN);\
  432. }
  433. use(print_e,Cell*,,E0)
  434. use(print_b,Cell*,-,B0)
  435. use(print_h,Cell*,,H0)
  436. use(print_tr,Cell*,-,TR0)
  437. use(print_p,Instr*,,P0)
  438. use(print_r,Cell*,,R0)
  439. #undef use
  440.  
  441. void print_reg(char* reg_name)
  442. {
  443.   switch (reg_name[0]) {
  444. #define use(ch,Function,PTR)\
  445.   case 'ch':\
  446.     Function(PTR);\
  447.       break;
  448.     use(e,print_e,E)
  449.     use(b,print_b,B)
  450.     use(p,print_p,P) 
  451.     use(h,print_h,H)
  452.     use(t,print_tr,TR)
  453.     use(r,print_r,R)
  454. #undef use
  455.   }
  456. }
  457.  
  458. void PrintReg(int atom)
  459. {
  460.   print_reg((char*) atom); cout << "\n";
  461. }
  462.  
  463. void print_env(Cell* E)
  464. {
  465.   cerr << "(" << (E - E0) << ")  ";
  466.   cerr << "B: "; print_b(cellp(E[B_ENV_OFFSET])); cerr << "\t";
  467.   cerr << "E: ("; print_e(cellp(E[E_ENV_OFFSET])); cerr << ",";
  468.   cerr << instrp(E[P_ENV_OFFSET])->arg2; cerr << ")\t";
  469.   cerr << "P: "; print_p(instrp(E[P_ENV_OFFSET])); cerr << "\n";
  470. }
  471.  
  472. struct E_chain {
  473.   CellPtr e;
  474.   CellPtr b;
  475.   E_chain(CellPtr E, CellPtr B);
  476.   CellPtr next();
  477.   void next_be();
  478. };
  479.  
  480. E_chain::E_chain(CellPtr E, CellPtr B)
  481. {
  482.   e = E;
  483.   b = B;
  484. }
  485.  
  486. CellPtr E_chain::next()
  487. {
  488.   CellPtr result = e;
  489.   e = cellp(e[E_ENV_OFFSET]);
  490.   if (e < cellp(b[E_CP_OFFSET])) {
  491.     e = cellp(b[E_CP_OFFSET]);
  492.     b += FIXED_CP_SIZE + b[SIZE_CP_OFFSET];
  493.   }
  494.   return result;
  495. }
  496.  
  497. void print_env_variables(CellPtr from, CellPtr to)
  498. {
  499.   CellPtr Y = from;
  500.   if (from < to) {
  501.     cerr << "\t";
  502.     for (; from < to; from++) {
  503.       cerr << "Y" << (from - Y) << "->";
  504.       write_term(*from); cerr << "; ";
  505.     }
  506.     cerr << "\n";
  507.   }
  508. }
  509.  
  510. void PrintEnv(int n = 1)
  511. {
  512.   E_chain chain(E, B); 
  513.   CellPtr Y, Y0;
  514.   Y = chain.next();
  515.   Y0 = chain.next();
  516.   for (int i = 0; i < n; i++) {
  517.     print_env(Y);
  518.     if (print_xreg_flag)
  519.       print_env_variables(Y0,Y - E_TOP_OFFSET);
  520.     Y = Y0;
  521.     Y0 = chain.next();
  522.   }
  523. }
  524.  
  525. void print_cp(Cell* B)
  526. {
  527.   cerr << "(" << (B0 - B) << ")  ";
  528.   cerr << "E:  "; print_e(cellp(B[E_CP_OFFSET])); cerr << "\t";
  529.   cerr << "H:  "; print_h(cellp(B[H_CP_OFFSET])); cerr << "\t";
  530.   cerr << "TR: "; print_tr(cellp(B[TR_CP_OFFSET])); cerr << "\t";
  531.   cerr << "P:  "; print_p(instrp(B[P_CP_OFFSET])); cerr << "\t";
  532.   cerr << "size: " << B[SIZE_CP_OFFSET] << "\n\t";
  533.   int i0 = B[SIZE_CP_OFFSET];
  534.   if (print_xreg_flag) {
  535.     for (int i = 0; i < i0; i++) {
  536.       cerr << "X" << i << "->";
  537.       write_term(B[X1_CP_OFFSET + i]);
  538.       cerr << "; ";
  539.     }
  540.     cerr << "\n";
  541.   }
  542. }
  543.  
  544. struct B_chain {
  545.   CellPtr b;
  546.   B_chain(CellPtr B) {b = B;}
  547.   void next() {
  548.     b += FIXED_CP_SIZE + b[SIZE_CP_OFFSET];
  549.   }
  550. };
  551.  
  552. void PrintCp(int n=0)
  553. {
  554.   B_chain chain(B);
  555.   for (int i = 0; i < n; i++) {
  556.     print_cp(chain.b);
  557.     chain.next();
  558.   }
  559. }
  560.  
  561. void print_records(char* name)
  562. {
  563.   switch (name[0]) {
  564.   case 'e':
  565.     print_env(E);
  566.     break;
  567.   case 'b':
  568.     print_cp(B);
  569.     break;
  570.   }
  571. }
  572.  
  573. void PrintRecords(int atom)
  574. {
  575.   print_records((char*) atom);
  576. }
  577.  
  578.  /* CONTROL  */
  579.  
  580. static jmp_buf top_level_env;
  581.  
  582. void top_level()
  583. {
  584.   setjmp(top_level_env);
  585.   for (;;) {
  586.     cerr << prompt;
  587.     command_scanner.next_line();
  588.     if (command_scanner.status == SCAN_EOF) {
  589.       cerr << "Bye bye\n";
  590.       exit(0);
  591.     }
  592.     execute_command();
  593.   }
  594. }
  595.  
  596. void service_interrupt()
  597. {
  598.   static int interrupt_counter = 0;
  599.   interrupt_counter++;
  600.   cerr << "\t\t\t *** Interrupt ***\n";
  601.   if (interrupt_counter > 8) exit(1);
  602.   top_level_normal_termination();
  603. }
  604.  
  605. void service_illegal_instruction()
  606. {
  607.   cerr << "\t\t\t *** Illegal Instruction ***\n";
  608.   top_level_normal_termination();
  609. }
  610.  
  611. void service_bus_error()
  612. {
  613.   cerr << "\t\t\t *** Bus Error ***\n";
  614.   top_level_normal_termination();
  615. }
  616.  
  617. void service_segmentation_fault()
  618. {
  619.   cerr << "\t\t\t *** Segmentation Fault ***\n";
  620.   top_level_normal_termination();
  621. }
  622.  
  623. void top_level_error(char* s) 
  624. {
  625.   if (s == 0)
  626.     s = "Error has occurred";
  627.   cerr << s << "\n";
  628.   top_level_normal_termination();
  629. }
  630.  
  631. void top_level_failure() 
  632. {
  633.   cerr << "\t\t\t*** FAIL *** \n";
  634.   top_level_normal_termination();
  635. }
  636.  
  637. void top_level_success() 
  638. {
  639.   cerr << "\t\t\t*** SUCCESS *** \n";
  640.   top_level_normal_termination();
  641. }
  642.  
  643. void top_level_normal_termination()
  644. {
  645.   longjmp(top_level_env, 0);
  646. }
  647.  
  648. void out_of_store()
  649. {
  650.   cerr << "memory exhausted\n";
  651.   exit(1);
  652. }
  653.  
  654. void AccessDataBase(Cell cnst)
  655. {
  656.   extern void access(Cell, Cell);
  657.   Cell var = make_ptr(TAGREF, H++);
  658.   access(cnst, var);
  659.   write_term(var);
  660. }
  661.  
  662. void print_heap_cell(Cell c, CellPtr Base)
  663. {
  664.   switch(get_tag(c)) {
  665.   case TAGREF:
  666.     cout << "REF    @" << addr(c) - Base << "\n";
  667.     break;
  668.   case TAGSTRUCT:
  669.     cout << "STRUCT @" << addr(c) -  Base << "\n";
  670.     break;
  671.   case TAGLIST:
  672.     cout << "LIST   @" << addr(c) - Base << "\n";
  673.     break;
  674.   case TAGCONST:
  675.     if (is_int(c))
  676.       cout << "INT    " << (c >> 3) << "\n";
  677.     else
  678.       cout << "ATOM   " << ((char*) c) << "\n";
  679.     break;
  680.   }    
  681. }
  682.  
  683. void PrintHeap(int from)
  684. {
  685.   for (int i = 0; i < BREADTH_LIMIT; i++) {
  686.     printf("%5d: ", i + from);
  687.     print_heap_cell(H0[i + from], H0);
  688.   }
  689. }
  690.  
  691. void PrintAssert(Cell cst)
  692. {
  693.   extern Cell assert_address_and_size(Cell, int&);
  694.   int size;
  695.   Cell value = assert_address_and_size(cst, size);
  696.   print_heap_cell(value, R0);
  697.   if (get_tag(value) != TAGCONST) {
  698.     CellPtr from = addr(value);
  699.     for (int i = 0; i < size; i++) {
  700.       printf("%5d: ", i + from - R0);
  701.       print_heap_cell(from[i], R0);
  702.     }
  703.   }
  704. }
  705.  
  706. void Echo(Cell atom)
  707. {
  708.   cout << get_string(atom) << "\n";
  709. }
  710.  
  711. void PrintStringTable(int)
  712. {
  713.   SCAN.print();
  714. }
  715.  
  716. void SelectGc(Cell atom)
  717. {
  718. #ifdef WITH_GC
  719.   char* gc = (char*) atom;
  720.   switch (*gc) {
  721.   case 's':
  722.     WHICH_GC = MARK_COMPACT;
  723.     break;
  724.   case 'c':
  725.     WHICH_GC = MARK_COPY;
  726.     break;
  727.   case 't':
  728.     WHICH_GC = MARK_THRESHOLD;
  729.     break;
  730.   case 'v':
  731.     WHICH_GC = MARK_COPY_FAST_COPY;
  732.     break;
  733.   case 'f':
  734.     WHICH_GC = MARK_COMPACT_FAST_COPY;
  735.     break;
  736.   case '?':
  737.   case 'h':
  738.     cerr << "[sct]: mark and compact (sweep), mark and copy, threshold\n";
  739.     cerr << "[vf]: mark-copy and fast copy; mark-compact and fast copy\n";
  740.     break;
  741.   default:
  742.     switch (WHICH_GC) {
  743.     case MARK_COPY:
  744.       cerr << "mark and copy [c], window=" << window_size / 256 << "\n";
  745.       break;
  746.     case MARK_COMPACT:
  747.       cerr << "mark and compact [s], window=" << window_size / 256 << "\n";
  748.       break;
  749.     case MARK_THRESHOLD:
  750.       cerr << "select copy or sweep, threshold [t], window=" 
  751.     << window_size / 256 << "\n";
  752.       break;
  753.     case MARK_COPY_FAST_COPY:
  754.       cerr << "mark-copy, and fast copy [v], window="
  755.     << window_size / 256 << "\n";
  756.       break;
  757.     case MARK_COMPACT_FAST_COPY:
  758.       cerr << "mark-compact, and fast copy [f], window="
  759.     << window_size / 256 << "\n";
  760.       break;
  761.     default:
  762.       cerr << "[sct]: mark and compact (sweep), mark and copy, threshold\n";
  763.       cerr << "[vf]: mark-copy and fast copy; mark-compact and fast copy\n";
  764.       break;
  765.     }
  766.   }
  767. #endif
  768. }
  769.  
  770. void TraceGc(int)
  771. {
  772. #ifdef WITH_GC
  773.   DISPLAY_GC = 1 - DISPLAY_GC;
  774. #endif
  775. }
  776.  
  777. void SetWindowSize(int size)
  778. {
  779. #ifdef WITH_GC
  780.   window_size = size * 256;
  781. #endif
  782. }
  783.  
  784. void SetGcLimit(int limit)
  785. {
  786. #ifdef WITH_GC
  787.   CHECK_GC_LIMIT = 1 - CHECK_GC_LIMIT;
  788.   GC_COUNT_LIMIT = limit;
  789. #endif
  790. }
  791.  
  792. void get_os_data()
  793. {
  794.   extern void getrusage(...);
  795.   struct rusage os_data;
  796.   struct timeval from = os_data.ru_utime;
  797.   getrusage(RUSAGE_SELF, &os_data);
  798.   struct timeval os_time = os_data.ru_utime;
  799.   float mstime = (float) os_time.tv_usec / 1000000 + os_time.tv_sec;
  800.   printf("%.1fu ", mstime);
  801.   os_time = os_data.ru_stime;
  802.   mstime = (float) os_time.tv_usec / 1000000 + os_time.tv_sec;
  803.   printf("%.1fs ", mstime);
  804.   printf("%dpr ", os_data.ru_minflt);
  805.   printf("%dpf ", os_data.ru_majflt);
  806.   printf("%dirss ", os_data.ru_idrss);
  807.   printf("%dmrss \n", os_data.ru_maxrss);
  808. }  
  809.  
  810. void GetGcData(int)
  811. {
  812. #ifdef WITH_GC
  813.   /* scanned, scanned by copy, fraction, survivors, fraction */
  814.  /* trail scanned, survivors, fraction */
  815.   if (gc_scanned == 0) {
  816.     top_level_error("Run a program with GC first");
  817.   }
  818.   printf("time in gc: %.3f mem recovered: %d\n", 
  819.      gc_time, gc_scanned - gc_survivors);
  820.   switch (WHICH_GC) {
  821.   case MARK_COPY:
  822.   case MARK_THRESHOLD:
  823.   case MARK_COPY_FAST_COPY:
  824.   case MARK_COMPACT_FAST_COPY:
  825.     printf("%d & %d & %d & %2.1f & %d & %2.1f & %d & %d & %2.1f\n",
  826.        window_size / 256,
  827.        gc_scanned,
  828.        gc_copy_scanned,
  829.        (float) gc_copy_scanned * 100 / gc_scanned,
  830.        gc_survivors,
  831.        (float) gc_survivors * 100 / gc_scanned,
  832.        tr_scanned,
  833.        tr_survivors,
  834.        (float) tr_survivors * 100 / tr_scanned);
  835.     break;
  836.   case MARK_COMPACT:
  837.     printf("%d & %d & %d & %2.1f & %d & %d & %2.1f\n",
  838.        window_size / 256,
  839.        gc_scanned,
  840.        gc_survivors,
  841.        (float) gc_survivors * 100 / gc_scanned,
  842.        tr_scanned,
  843.        tr_survivors,
  844.        (float) tr_survivors * 100 / tr_scanned);
  845.     break;
  846.   default:
  847.     cerr << "[sc]: mark and compact (sweep), mark and copy\n";
  848.     break;
  849.   }
  850. #endif
  851.   get_os_data();
  852. }
  853.